{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Inititialization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First qkit is imported (see \"Basic_QKIT_start.ipynb\").  \n",
    "This reads your config files and creates the qkit.cfg object from which we read the path to the sample data.\n",
    "\n",
    "Required packages are:\n",
    "\n",
    "pyplot : To plot the data and fitting results.  \n",
    "pointtracker : To track traces of dips or peaks in two dimensional data.  \n",
    "avoided_crossing_fit : To fit hybridized spectra and get the eigenenergies and coupling strengths."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note**: The pointtracker requires peakutils to be installed (For example via 'pip install peakutils') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import qkit\n",
    "from qkit.storage import store\n",
    "\n",
    "# Plotting\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "# Import pointtracker for finding peaks/dips in the data.\n",
    "from qkit.analysis.pointtracker import pointtracker as pt\n",
    "\n",
    "# Import the anticrossing fit routine.\n",
    "from qkit.analysis.avoided_crossing_fit import ACF as acf"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Loading and plotting Sample Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The sample data is stored in the hdf file format used for measurements with qkit and read using the qkit.storage libraries.\n",
    "\n",
    "The chosen dataset is a noisy one on purpose to demonstrate the capabilities of the pointtracker."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Create an object containing the hdf dataset.\n",
    "# The code in the brackets returns an absolute path to the sample data in the present qkit installation.\n",
    "h5 = store.Data(qkit.cfg['rootdir']+'\\\\doc\\\\sample_data\\\\P8PPH2_anticrossing_sample_data.h5')\n",
    "\n",
    "# Read the numpy arrays for the two coordinates and the amplitude data.\n",
    "current = h5.data.current[:]\n",
    "freq = h5.data.frequency[:]\n",
    "amp = h5.data.amplitude[:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Plot the imported sample data.\n",
    "plt.pcolormesh(current, freq, amp.T)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An avoided crossing can be seen in the plotted image. The noisy backgrond however makes it non-trivial to fit, as the shape of the anticrossing does not correspond to obvious dips or peaks in the data."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Point Tracking"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The idea of the pointtracker is to follow a trace of dips or peaks through a dataset.\n",
    "\n",
    "Extracting the shape of an avoided crossing is not is only application. Another example could be to track a shifting resonance dip in a resonator powerscan, if only a small region of the dip can be fitted."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Create an instance of the pointtracker.\n",
    "tracking = pt()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Peakutils is used to determine the peaks or dips in a narrow span that is internally set and shifted through the dataset by the pointtracker.\n",
    "\n",
    "Here, the threshold for a feature to be identified as peak or dip is increased. This has to be adapted to the properties of the analyzed data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Set peakutils search parameters.\n",
    "tracking.set_peakutils_params(thres=0.95, min_dist=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Pass sample data to pointtracker.\n",
    "tracking.set_data(current,freq,amp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The pointtracker has to be told where to start peak or dip detection. From its starting point, it recursively follows a trace in both directions until the boundaries of the dataset are reached."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Tracking branch one"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Set starting point for peak detection (approximate arbitrary point on one of the branches of the anticrossing).\n",
    "# Set span in which peaks or dips should be detected (width of the followed trace).\n",
    "# Tell the pointtracker to look for dips (default).\n",
    "tracking.set_searchparams([-7, 6.65e9], 100e6, dips=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Start the tracking.\n",
    "tracking.start_tracking()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sometimes the pointtracker will find no or more than one peak in a span he is detecting in. This is printed here.\n",
    "\n",
    "In the case of more than one peak or dip, it choses the first one. As the detected points are used for fits later, the precision is sufficient.\n",
    "\n",
    "If no or the wrong features are detected, the parameters (peakutils threshold, pointtracker span) should be adapted.\n",
    "\n",
    "To check if the results are ok, it can be plotted:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Plot the found trace.\n",
    "tracking.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The first arm in this example has been detected well. Some points are off in noisy traces. These are removed later.\n",
    "\n",
    "First, do the same with the second branch."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Tracking branch two"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Set starting point for peak detection (approximate arbitrary point on one of the branches of the anticrossing).\n",
    "# Set span in which peaks or dips should be detected (width of the followed trace).\n",
    "tracking.set_searchparams([-5.8,6.56e9], 100e6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Start the tracking.\n",
    "tracking.start_tracking()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Plot both found trace.\n",
    "tracking.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Deleting traces and points"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Each time the pointtracker is run, a new trace is added. From these, the one with the best results can be chosen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# If one of the found traces was not satisfactory it can be deleted with:\n",
    "#tracking.del_trace(<trace_nr>)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the chosen traces, some points might be not satiscatory. These can be removed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Not all found points are correctly detected. These points are removed here:\n",
    "tracking.del_points(indices=[0,4,5,7], trace=0)\n",
    "tracking.del_points(indices=[0,10,11,12], trace=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Plot again the corrected traces.\n",
    "tracking.plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If the points to be deleted are at the ends of a trace and counting their indices is difficult, the ends of a trace can be cut from both sides."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Cutting 0 points from the 'high' end of the 'last' trace.\n",
    "tracking.cut(amount=0, trace=-1, end='high')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Results"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Internally, the pointtracker works only with the indices of the data coordinates in the data arrays.\n",
    "\n",
    "Fitting to the resutls requires a translation back into the dimensions of the data.  \n",
    "This can be done with the 'get_results' function.  \n",
    "It returns the found points in two lists of arrays.  \n",
    "One list for the x-coordinates of the points in an array for each trace and one list for the y-coordinates in an array for each trace."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# x and y values of the found points can be read via:\n",
    "tracking.get_results()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If the indices of the points are required, they can be accessed directly via the variables 'x_results' and 'y_results',  \n",
    "each containing arrays of the indices for each trace."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "tracking.x_results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "tracking.y_results"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Anticrossing Fit"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The detected dips can now be fitted with the avoided crossing fit routine."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Create an instance of the anticrossing fit.\n",
    "ac_fit = acf()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Store the results of the pointtracker into variables containing x and y data of the found peaks above.\n",
    "xfit_data = tracking.get_results()[0]\n",
    "yfit_data = tracking.get_results()[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setting functions and start parameterts"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The avoided crossing fit routine fits an anticrossing by diagonilizing the Hamiltonian.\n",
    "\n",
    "The functions describing the undressed eigenenergies of the two systems have to be defined.  \n",
    "Some common functions are provided in the class (constant, linear function, parabola, transmon_f01).\n",
    "\n",
    "If required, a function can also be defined externally and fed into the class.\n",
    "\n",
    "At least two functions for two interacting systems are required.\n",
    "However, the routine is generalized for an abritrary number of interacting systems."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Set type of functions which form the anticrossing.\n",
    "# In this example the anticrossing is formed by a constant line (fixed frequency) and a linear function.\n",
    "# Note: This case shown here is also the default if no functions are defined.\n",
    "ac_fit.set_functions(ac_fit.constant_line, ac_fit.straight_line)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Pass the data of the peaks to the anticrossing fit and set start parameters for the fit.\n",
    "# The start parameters are required for the provided functions (one for the constant, two for the lienar function)\n",
    "# and for the coupling of both (last parameter).\n",
    "ac_fit.set_all(xfit_data, yfit_data, p0 = [6.62e9, 4e8, 9e9, 100e6])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Plot the anticrossing with the initial parameters as chosen above.\n",
    "ac_fit.plot_init_pars()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If the resulting anticrossing is very different from the data, the parameters might be adapted."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fitting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Execute the anticrossing fit.\n",
    "ac_fit.fit()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# Plot the fitted anticrossing and the raw data.\n",
    "fig, axes = plt.subplots(figsize=(16,8))\n",
    "plt.pcolormesh(current,freq,amp.T)\n",
    "plt.colorbar()\n",
    "ac_fit.plot_results()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The fit results are stored in a tuple 'ac_fit.results'.\n",
    "\n",
    "The first element denotes the index of the system/function, the second one denotes function parameter, the third one is the value, and the last one is the fit error (least square error).\n",
    "\n",
    "This representation is chosen to achieve a better readability, especially in the case of a large number of coupled systems."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "ac_fit.results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
